package com.wenlin.myproduction.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.CountDownTimer;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.wenlin.myproduction.R;
import com.wenlin.myproduction.util.Checker;
import com.wenlin.myproduction.util.UI;

import java.util.List;
import java.util.concurrent.ExecutionException;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * 跑马灯控件
 *
 * @author 文琳
 * @time 2020/12/07 13:58
 * @desc 跑马灯
 */
public class MarqueeView extends View {
    private static final int ANIM_DUR = 1000;//条目切换的动画时间
    private static final int SHOW_DUR = 1500;//跑马灯条目停留一小会儿时间，然后被下一条顶上去
    private int viewWidth = (int) UI.getPx(R.dimen.wpx260);
    private int viewHeight = (int) UI.getPx(R.dimen.wpx240);
    private int itemHeight = (int) UI.getPx(R.dimen.wpx110);
    private Paint paint;
    private TextPaint textPaint;
    private int colorFt;
    private int colorText;
    private float offsetText = UI.getPx(R.dimen.wpx3);//文字竖直偏移
    private float textSize = UI.getPx(R.dimen.wpx24);
    private float radius = UI.getPx(R.dimen.wpx28);
    private float headRadius = UI.getPx(R.dimen.wpx20);
    private float margin = UI.getPx(R.dimen.wpx30);
    private float margin50 = UI.getPx(R.dimen.wpx50);
    private float nameCenterY = UI.getPx(R.dimen.wpx36);
    private float giftCenterY = UI.getPx(R.dimen.wpx72);
    private float nameCenterY2 = UI.getPx(R.dimen.wpx166);
    private float giftCenterY2 = UI.getPx(R.dimen.wpx202);
    private float item2StartY = UI.getPx(R.dimen.wpx130);
    private float itemMargin = UI.getPx(R.dimen.wpx20);
    private Rect rectName, rectDesc;
    private ValueAnimator valueAnimator;
    private float valueFloat;
    private int index;
    private List<MarqueeBean> list;
    private CountDownTimer timer;
    private Bitmap bitmapDefault;
    private PorterDuffXfermode porterDuffXfermode;

    public MarqueeView(Context context) {
        this(context, null);
    }

    public MarqueeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MarqueeView);
        colorFt = ta.getColor(R.styleable.MarqueeView_mv_ft_color, Color.parseColor("#fff3f3f3"));//UI.getColor(R.color.myBg)
        colorText = ta.getColor(R.styleable.MarqueeView_mv_text_color, Color.parseColor("#ff333333"));//UI.getColor(R.color.myTitle)
        ta.recycle();
        initialize();
    }

    /**
     * 初始化
     */
    private void initialize() {
        //主画笔
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        //文字画笔
        textPaint = new TextPaint();
        textPaint.setColor(colorText);
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        textPaint.setTextSize(textSize);
        //渐变色
        LinearGradient linearGradient = new LinearGradient(0f, 0f, viewWidth, 0f,
                Color.parseColor("#ff1dc9e3"),//蓝色
                Color.parseColor("#ff1de6ba"),//绿色
                Shader.TileMode.CLAMP
        );
        paint.setShader(linearGradient);
        //其他
        rectName = new Rect();
        rectDesc = new Rect();

        bitmapDefault = getBitmapDefault();//不写这句也行，因为在调用的时候都是使用getBitmapDefault()，而不是直接调用bitmapDefault

        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);//模式：显示前景图并取交集（IN）。（SRC source表示源图片，背景图是DST destination目的地）
    }

    /**
     * 设置数据
     *
     * @param newList 数据集合
     */
    public void setData(List<MarqueeBean> newList) {
        UI.releaseTimer(timer);
        UI.releaseValueAnimator(valueAnimator);
        //释放bitmap
        if (Checker.hasList(list)) {
            for (int i = 0; i < list.size(); i++) {
                MarqueeBean bean = list.get(i);
                Bitmap bitmap = bean.getBitmap();
                if (bitmap != null && !bitmap.isRecycled()) {
                    bitmap.recycle();
                    bitmap = null;
                    list.get(i).setBitmap(null);
                }
            }
            list.clear();
        }
        list = newList;
        handleHeadBitmap();
        tryStartTimer();
    }

    /**
     * 下载头像图片
     */
    private void handleHeadBitmap() {
        if (Checker.hasNoList(list)) return;
        for (int i = 0; i < list.size(); i++) {
            MarqueeBean mb = list.get(i);
            Observable.just(mb.getHead()).map(url -> {
                Bitmap bitmap = null;
                try {
                    if (Checker.notNull(getContext()))
                        bitmap = Glide.with(getContext()).asBitmap().load(url).submit().get();
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
                return bitmap;
            }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Bitmap>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
//                    LogUtils.e(mb.getHead() + "头像图片异常");
                }

                @Override
                public void onNext(Bitmap bitmap) {
                    if (Checker.isNull(getContext())){
                        return;
                    }
                    if (bitmap == null) {
//                        LogUtils.e(mb.getHead() + "头像图片异常");
                        bitmap = getBitmapDefault();
                    }
                    //处理图片，进行缩放
                    for (int j = 0; j < list.size(); j++) {
                        MarqueeBean temp = list.get(j);
                        if (temp.getHead().equals(mb.getHead())) {
                            list.get(j).setBitmap(handleBitmap(bitmap, UI.getPx(R.dimen.wpx40), UI.getPx(R.dimen.wpx40)));
                            break;
                        }
                    }
                    postInvalidate();
                }
            });
        }
    }

    /**
     * 获取默认头像的位图
     *
     * @return 所求
     */
    private Bitmap getBitmapDefault() {
        if (Checker.isNull(bitmapDefault) || bitmapDefault.isRecycled()) {
            bitmapDefault = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_default_head_girl);
            bitmapDefault = handleBitmap(bitmapDefault, UI.getPx(R.dimen.wpx40), UI.getPx(R.dimen.wpx40));
        }
        return bitmapDefault;
    }

    /**
     * 尝试开始轮播中奖列表了
     */
    private void tryStartTimer() {
        index = -2;
        UI.releaseTimer(timer);
        if (Checker.hasList(this.list))
            timer = new CountDownTimer(Integer.MAX_VALUE, SHOW_DUR + ANIM_DUR) {
                @Override
                public void onTick(long millisUntilFinished) {
                    index += 2;
                    startAnimation();
                }

                @Override
                public void onFinish() {
                    //应该用不到
                }
            }.start();
    }

    /**
     * 生成新的Bitmap图片
     *
     * @return 所求
     */
    private Bitmap handleBitmap(Bitmap bitmap, float newWidth, float newHeight) {
        Matrix matrix = new Matrix();//创建一个处理图片的类
        int width = bitmap.getWidth();//获取图片本身的大小(宽)
        int height = bitmap.getHeight();//获取图片本身的大小(高)
        float wS, hS;
        if (width >= height) {
            hS = newHeight / height;//缩放比---->这块注意这个是新的宽度/高度除以旧的宽度
            wS = hS;
        } else {
            wS = newWidth / width;//缩放比---->这块注意这个是新的宽度/高度除以旧的宽度
            hS = wS;
        }
        matrix.postScale(wS, hS);//这块就是处理缩放的比例
        //matrix.setScale(sX,sY);//缩放图片的质量sX表示宽0.5就代表缩放一半,sX同样
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    /**
     * 开始动画
     */
    private void startAnimation() {
        valueAnimator = ValueAnimator.ofFloat(viewHeight + itemMargin, 0);
        valueAnimator.addUpdateListener(animation -> {
            valueFloat = (float) animation.getAnimatedValue();
            invalidate();
        });
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.setDuration(ANIM_DUR);
        valueAnimator.start();
    }

    /**
     * 返回上一个的数据的第一项
     *
     * @return 所求
     */
    private MarqueeBean getLastFirst() {
        int lastFirst = index - 2;
        if (Checker.hasList(list)) lastFirst = lastFirst % list.size();
        if (lastFirst < 0) return null;
        return list.get(lastFirst);
    }

    /**
     * 返回上一个的数据的第二项
     *
     * @return 所求
     */
    private MarqueeBean getLastSecond() {
        int lastSecond = index - 1;
        if (Checker.hasList(list)) lastSecond = lastSecond % list.size();
        if (lastSecond < 0) return null;
        return list.get(lastSecond);
    }

    /**
     * 返回当前的数据的第一项
     *
     * @return 所求
     */
    private MarqueeBean getNewFirst() {
        int newFirst = index;
        if (Checker.hasList(list)) newFirst = newFirst % list.size();
        if (newFirst < 0) return null;
        return list.get(newFirst);
    }

    /**
     * 返回当前的数据的第二项
     *
     * @return 所求
     */
    private MarqueeBean getNewSecond() {
        int newSecond = index + 1;
        if (Checker.hasList(list)) newSecond = newSecond % list.size();
        if (newSecond < 0) return null;
        return list.get(newSecond);
    }

    /**
     * 返回加密后的名字。原需求为：最多显示4个字，首字显示，其他字以*出现。
     *
     * @param name 名字
     * @return 所求
     */
    private String getFormatName(String name) {
        if (Checker.hasNoWord(name)) return "";
        name = name.trim();//处理空格
        StringBuilder sb = new StringBuilder();
        if (name.length() > 0) sb.append(name.substring(0, 1));
        if (name.length() > 1)
            for (int i = 1; i < (Math.min(name.length(), 4)); i++) sb.append("*");
        return sb.toString();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (Checker.hasList(list)) {
            //加载第一个
            MarqueeBean lastFirst = getLastFirst();
            if (Checker.notNull(lastFirst)) {
                canvas.drawRoundRect(0, -itemMargin - viewHeight + valueFloat, viewWidth, -itemMargin - viewHeight + valueFloat + itemHeight, radius, radius, paint);
                //头像
                canvas.saveLayerAlpha(margin, nameCenterY - headRadius - itemMargin - viewHeight + valueFloat, margin + 2 * headRadius, nameCenterY + headRadius - itemMargin - viewHeight + valueFloat, 255);
                canvas.drawCircle(margin + headRadius, nameCenterY - itemMargin - viewHeight + valueFloat, headRadius, paint);
                paint.setXfermode(porterDuffXfermode);
                if (Checker.isNull(lastFirst.getBitmap())) lastFirst.setBitmap(getBitmapDefault());
                canvas.drawBitmap(lastFirst.getBitmap(), margin, nameCenterY - lastFirst.getBitmap().getHeight() / 2f - itemMargin - viewHeight + valueFloat, paint);
                paint.setXfermode(null);
                canvas.restore();
                //中奖人
                String strName = getFormatName(lastFirst.getName());
                textPaint.getTextBounds(strName, 0, strName.length(), rectName);
                canvas.drawText(strName, margin + margin50, nameCenterY + rectName.height() / 2f - itemMargin - viewHeight + valueFloat - offsetText, textPaint);
                //中奖文案
                String strDesc = lastFirst.getGift();
                String strTemp = strDesc;
                textPaint.getTextBounds(strDesc, 0, strDesc.length(), rectDesc);
                while (rectDesc.width() > (viewWidth - margin - margin / 2f)) {//描述文字左边距margin，右边距为margin的一半
                    strDesc = strDesc.substring(0, strDesc.length() - 1);
                    strTemp = strDesc + "...";
                    textPaint.getTextBounds(strTemp, 0, strTemp.length(), rectDesc);
                }
                strDesc = strTemp;
                canvas.drawText(strDesc, margin, giftCenterY + rectDesc.height() / 2f - itemMargin - viewHeight + valueFloat - offsetText, textPaint);
            }
            //加载第二个
            MarqueeBean lastSecond = getLastSecond();
            if (Checker.notNull(lastSecond)) {
                canvas.drawRoundRect(0, item2StartY - itemMargin - viewHeight + valueFloat, viewWidth, item2StartY - itemMargin - viewHeight + valueFloat + itemHeight, radius, radius, paint);
                //头像
                canvas.saveLayerAlpha(margin, nameCenterY2 - headRadius - itemMargin - viewHeight + valueFloat, margin + 2 * headRadius, nameCenterY2 + headRadius - itemMargin - viewHeight + valueFloat, 255);
                canvas.drawCircle(margin + headRadius, nameCenterY2 - itemMargin - viewHeight + valueFloat, headRadius, paint);
                paint.setXfermode(porterDuffXfermode);
                if (Checker.isNull(lastSecond.getBitmap()))
                    lastSecond.setBitmap(getBitmapDefault());
                canvas.drawBitmap(lastSecond.getBitmap(), margin, nameCenterY2 - lastSecond.getBitmap().getHeight() / 2f - itemMargin - viewHeight + valueFloat, paint);
                paint.setXfermode(null);
                canvas.restore();
                //中奖人
                String strName = getFormatName(lastSecond.getName());
                textPaint.getTextBounds(strName, 0, strName.length(), rectName);
                canvas.drawText(strName, margin + margin50, nameCenterY2 + rectName.height() / 2f - itemMargin - viewHeight + valueFloat - offsetText, textPaint);
                //中奖文案
                String strDesc = lastSecond.getGift();
                String strTemp = strDesc;
                textPaint.getTextBounds(strDesc, 0, strDesc.length(), rectDesc);
                while (rectDesc.width() > (viewWidth - margin - margin / 2f)) {
                    strDesc = strDesc.substring(0, strDesc.length() - 1);
                    strTemp = strDesc + "...";
                    textPaint.getTextBounds(strTemp, 0, strTemp.length(), rectDesc);
                }
                strDesc = strTemp;
                canvas.drawText(strDesc, margin, giftCenterY2 + rectDesc.height() / 2f - itemMargin - viewHeight + valueFloat - offsetText, textPaint);
            }
            //加载第三个
            MarqueeBean newFirst = getNewFirst();
            if (Checker.notNull(newFirst)) {
                canvas.drawRoundRect(0, valueFloat, viewWidth, valueFloat + itemHeight, radius, radius, paint);
                //头像
                canvas.saveLayerAlpha(margin, nameCenterY - headRadius + valueFloat, margin + 2 * headRadius, nameCenterY + headRadius + valueFloat, 255);
                canvas.drawCircle(margin + headRadius, nameCenterY + valueFloat, headRadius, paint);
                paint.setXfermode(porterDuffXfermode);
                if (Checker.isNull(newFirst.getBitmap())) newFirst.setBitmap(getBitmapDefault());
                canvas.drawBitmap(newFirst.getBitmap(), margin, nameCenterY - newFirst.getBitmap().getHeight() / 2f + valueFloat, paint);
                paint.setXfermode(null);
                canvas.restore();
                //中奖人
                String strName = getFormatName(newFirst.getName());
                textPaint.getTextBounds(strName, 0, strName.length(), rectName);
                canvas.drawText(strName, margin + margin50, nameCenterY + rectName.height() / 2f + valueFloat - offsetText, textPaint);
                //中奖文案
                String strDesc = newFirst.getGift();
                String strTemp = strDesc;
                textPaint.getTextBounds(strDesc, 0, strDesc.length(), rectDesc);
                while (rectDesc.width() > (viewWidth - margin - margin / 2f)) {
                    strDesc = strDesc.substring(0, strDesc.length() - 1);
                    strTemp = strDesc + "...";
                    textPaint.getTextBounds(strTemp, 0, strTemp.length(), rectDesc);
                }
                strDesc = strTemp;
                canvas.drawText(strDesc, margin, giftCenterY + rectDesc.height() / 2f + valueFloat - offsetText, textPaint);
            }
            //加载第四个
            MarqueeBean newSecond = getNewSecond();
            if (Checker.notNull(newSecond)) {
                canvas.drawRoundRect(0, item2StartY + valueFloat, viewWidth, item2StartY + valueFloat + itemHeight, radius, radius, paint);
                //头像
                canvas.saveLayerAlpha(margin, nameCenterY2 - headRadius + valueFloat, margin + 2 * headRadius, nameCenterY2 + headRadius + valueFloat, 255);
                canvas.drawCircle(margin + headRadius, nameCenterY2 + valueFloat, headRadius, paint);
                paint.setXfermode(porterDuffXfermode);
                if (Checker.isNull(newSecond.getBitmap())) newSecond.setBitmap(getBitmapDefault());
                canvas.drawBitmap(newSecond.getBitmap(), margin, nameCenterY2 - newSecond.getBitmap().getHeight() / 2f + valueFloat, paint);
                paint.setXfermode(null);
                canvas.restore();
                //中奖人
                String strName = getFormatName(newSecond.getName());
                textPaint.getTextBounds(strName, 0, strName.length(), rectName);
                canvas.drawText(strName, margin + margin50, nameCenterY2 + rectName.height() / 2f + valueFloat - offsetText, textPaint);
                //中奖文案
                String strDesc = newSecond.getGift();
                String strTemp = strDesc;
                textPaint.getTextBounds(strDesc, 0, strDesc.length(), rectDesc);
                while (rectDesc.width() > (viewWidth - margin - margin / 2f)) {
                    strDesc = strDesc.substring(0, strDesc.length() - 1);
                    strTemp = strDesc + "...";
                    textPaint.getTextBounds(strTemp, 0, strTemp.length(), rectDesc);
                }
                strDesc = strTemp;
                canvas.drawText(strDesc, margin, giftCenterY2 + rectDesc.height() / 2f + valueFloat - offsetText, textPaint);
            }
        }else{
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//如果没有数据，就不显示任何内容，即把画布清空
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        UI.releaseTimer(timer);
        UI.releaseValueAnimator(valueAnimator);
        if (Checker.notNull(bitmapDefault) && !bitmapDefault.isRecycled()) {
            bitmapDefault.recycle();
            bitmapDefault = null;
        }
        //释放bitmap
        if (Checker.hasList(list)) {
            for (int i = 0; i < list.size(); i++) {
                MarqueeBean bean = list.get(i);
                Bitmap bitmap = bean.getBitmap();
                if (bitmap != null && !bitmap.isRecycled()) {
                    bitmap.recycle();
                    bitmap = null;
                    list.get(i).setBitmap(null);
                }
            }
            list.clear();
            list = null;
        }
    }

    public static class MarqueeBean implements Parcelable {
        public static final Creator<MarqueeBean> CREATOR = new Creator<MarqueeBean>() {
            @Override
            public MarqueeBean createFromParcel(Parcel source) {
                return new MarqueeBean(source);
            }

            @Override
            public MarqueeBean[] newArray(int size) {
                return new MarqueeBean[size];
            }
        };
        private String name;
        private String gift;
        private String head;
        private Bitmap bitmap;

        public MarqueeBean(String name, String gift, String head) {
            this.name = name;
            this.gift = gift;
            this.head = head;
        }

        protected MarqueeBean(Parcel in) {
            this.name = in.readString();
            this.gift = in.readString();
            this.head = in.readString();
            this.bitmap = in.readParcelable(Bitmap.class.getClassLoader());
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getGift() {
            return gift;
        }

        public void setGift(String gift) {
            this.gift = gift;
        }

        public String getHead() {
            return head;
        }

        public void setHead(String head) {
            this.head = head;
        }

        public Bitmap getBitmap() {
            return bitmap;
        }

        public void setBitmap(Bitmap bitmap) {
            this.bitmap = bitmap;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.name);
            dest.writeString(this.gift);
            dest.writeString(this.head);
            dest.writeParcelable(this.bitmap, flags);
        }
    }
}
